package org.com.sec.noncritical.enigma;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeMap;

/**
 * Implements a rotor functionality. Basically extends {@link ArrayList} but
 * adds some concrete functionality for the case.
 *
 * @author See <a href="the Google Code page of the easy-utils
 * library">http://code.google.com/p/easy-utils/</a> for collaborators and other
 * information.
 */
public final class Rotor extends ArrayList<Character> {

    private final TreeMap<Integer, Character> map = new TreeMap<>();
    private final ArrayList<Character> ALPHABET = new ArrayList<>();

    /**
     * Constructor method.
     *
     * @param startingLetter {@link Character} The letter that the rotor must
     * use as starting position.
     * @param mapping {@link String} The mapping for the rotor. In this example,
     * the rotors used will have the mappings I, II and III of the SWISS K
     * model.
     */
    protected Rotor(Character startingLetter, String mapping) {
        this.initializeAlphabet();

        char[] mappingChars = mapping.toCharArray();

        for (int i = 0; i < mappingChars.length; i++) {
            this.map.put(i, mappingChars[i]);
        }

        for (int i = this.ALPHABET.indexOf(startingLetter); i < this.ALPHABET.size(); i++) {
            this.add(this.ALPHABET.get(i));
        }

        for (Iterator<Character> it = this.ALPHABET.iterator(); it.hasNext();) {
            Character currentLetter = it.next();
            if (this.contains(currentLetter)) {
                break;
            }
            this.add(currentLetter);
        }
    }

    /**
     * Moves the rotor one position ahead.
     */
    protected void move() {
        this.add(this.remove(0));
    }

    /**
     * Provides the mutation of a given letter when going through this rotor.
     *
     * @param letter {@link Character} The source letter.
     * @return {@link Character} The new letter corresponding to the given one.
     */
    protected Character translate(Character letter) {
        return this.map.get(this.indexOf(letter));
    }

    /**
     * Provides the reverse mutation of a given letter when going through this
     * rotor.
     *
     * @param letter {@link Character} The source letter.
     * @return {@link Character} The new letter corresponding to the given one.
     */
    protected Character reverseTranslate(Character letter) {
        int index = 0;

        for (Iterator<Integer> it = this.map.keySet().iterator(); it.hasNext();) {
            if (this.map.get(it.next()) == letter) {
                break;
            }
            index++;
        }

        return this.get(index);
    }

    /**
     * Puts static data into a model alphabet which will be used for calculating
     * rotors rotations and some indexes.
     */
    private void initializeAlphabet() {
        for (int i = 0; i <= EnigmaMachine.getAlphabet().length(); i++) {
            this.ALPHABET.add(EnigmaMachine.getAlphabet().charAt(i));
        }
    }

    /**
     * Provides the currently selected letter.
     *
     * @return {@link Character} The currently selected letter in this rotor.
     */
    protected Character getCurrentlySelectedLetter() {
        return this.get(0);
    }
}
